--------------------------------------------------------------------------
-- 会员主题-抽奖模块
--#author:liuzhihong
--time:2022-06-14
--
--------------------------------------------------------------------------

-- 文件
local gg = require("modules.business_welfare.welfare_gg")
local config = require("modules.business_welfare.welfare_lua_config")
local uu = require("modules.commhm.utils")
local ns_account = require("modules.business_welfare.welfare_bridge")
local log = require("modules.commhm.log")
local t_yxcard = require("modules.business_welfare.yxcard.t_yxcard")
local op_log = require("modules.business_welfare.welfare_op_log")
local common_ssdb = require("modules.business_common.business_ssdb")
local code_conf = require("modules.business_welfare.welfare_code")
local ns_config = require("modules.business_welfare.welfare_config")
local common_uu = require("modules.business_common.business_utils")
local asset_mgr = require("modules.business_common.bridge.business_assetmgr")
local business_account = require("modules.business_common.business_account")
local http = require("modules.business_common.utils.business_http")
local welfare_gift = require("modules.business_welfare.welfare_gift")

-- 变量 开头定义优先级 系统库 > ngx > 自定义
local pairs = pairs
local ipairs = ipairs
local math = math
local math_abs = math.abs
local math_fmod = math.fmod
local math_floor = math.floor
local next = next
local table = table
local table_insert = table.insert
local tonumber = tonumber
local os = os
local os_date = os.date
local os_time = os.time
local ngx = ngx
local ngx_time = ngx.time
local error_code = code_conf.error_code

local op_type = {
    draw_free = 1, --免费抽
    draw_cost = 2 --消耗券去抽
}

local FOO = {
    _VERSION = "0.12.1",
    module_name = "vip_theme"
}

--------------------------------------------------
-- !@  取得抽奖的外围配置
local get_vip_theme_cfg = function()
    local conf = config.get_cfg("mission")
    if not conf then
        return nil
    end

    local tmp_vip = conf[25].vip_theme
    if not tmp_vip then
        return nil
    end

    return tmp_vip.luckdraw
end

--------------------------------------------------
-- !@ 是否在会员主题活动中
local vip_theme_active = function()
    local theme_cfg = get_vip_theme_cfg()
    if not theme_cfg then
        return false
    end

    local startTime = theme_cfg.startTime and common_uu.date_to_unix(theme_cfg.startTime) or 0
    local endtime = theme_cfg.endTime and common_uu.date_to_unix(theme_cfg.endTime) or 0
    local now = common_uu.hm.now()
    if now < startTime or now > endtime then
        return false
    end

    return true
end

-- !@ 获得抽奖DC数据
local get_data_dc = function(uin)
    local _uin = uin or ngx.ctx.m_params.uin
    if not ngx.ctx.draw_data then
        --拉取变量
        local ret, data = gg.private_hash_get_table_ssdb(_uin, _uin, common_ssdb.KEYS.VIP_LUCKDRAW)
        if ret == 0 and data then
            ngx.ctx.draw_data = data
        elseif error_code.ERROR_NO_DATA == ret then
            ngx.ctx.draw_data = {}
        else
            log.error(
                "error::get_data_dc private_hash_get_table_ssdb failed  vip_theme,ssdb_keyname =" ..
                    common_ssdb.KEYS.VIP_LUCKDRAW
            )
        end
    end
    ngx.ctx.draw_data.tdata = ngx.ctx.draw_data.tdata or {}
    return ngx.ctx.draw_data
end

-- !@判断是否是新活动
local is_new_huodong = function(tdata)
    if not tdata then
        return false
    end

    local theme_cfg = get_vip_theme_cfg()
    if not theme_cfg then
        return false
    end

    tdata.last_time = tdata.last_time or 0
    local startTime = theme_cfg.startTime and common_uu.date_to_unix(theme_cfg.startTime) or 0
    local endtime = theme_cfg.endTime and common_uu.date_to_unix(theme_cfg.endTime) or 0
    if tdata.last_time >= startTime and tdata.last_time <= endtime then
        return false
    end

    return true
end

-- !@ 检查及清零每日免费次数数据
local check_daily_freetimes = function(tdata)
    if not tdata then
        return
    end

    local now = uu.now()
    if common_uu.is_same_day(now, tdata.free_rcd_time) then
        return
    end
    tdata.free_times = 0
    tdata.free_times_vip = 0
    tdata.free_rcd_time = now
end

--[[
    tdata = {
        tickets = 0,  -- 抽奖券数
        present_times = 0,   -- 会员开通给予免费抽奖次数
        free_times   = 0,   -- 每日免费使用次数
        free_times_vip = 0, -- 使用会员免费次数
        free_rcd_time = 0,  -- 免费使用次数更新时间
        last_time = 0,      -- 最近一次操作数据时间
    }
]]
-- !@ 获得抽奖数据
local get_data = function(uin)
    local data = get_data_dc(uin)
    if is_new_huodong(data.tdata) then --不是同一个活动就清理数据
        data.tdata = {}
        data.tdata.last_time = uu.now()
        data.tdata.tickets = data.tdata.tickets or 0 -- 抽奖券数
        data.tdata.present_times = data.tdata.present_times or 0 -- 会员开通给予免费抽奖次数
        data.tdata.free_times = data.tdata.free_times or 0 -- 每日免费使用次数
        data.tdata.free_times_vip = data.tdata.free_times_vip or 0 -- 使用会员免费次数
        data.tdata.free_rcd_time = data.tdata.free_rcd_time or 0 -- 免费使用次数更新时间
        data.tdata.last_time = data.tdata.last_time or 0 -- 最近一次操作数据时间
    end
    check_daily_freetimes(data.tdata)
    --local draw_data = common_uu.table_copy(data.tdata or {})
    return data.tdata
end

-- !@ 设置抽奖数据
local set_data = function(uin, draw_data, bsave)
    local _uin = uin or ngx.ctx.m_params.uin
    ngx.ctx.draw_data = ngx.ctx.draw_data or {}
    ngx.ctx.draw_data.tdata = draw_data

    if bsave then
        return gg.private_hash_set_table_ssdb(_uin, _uin, common_ssdb.KEYS.VIP_LUCKDRAW, ngx.ctx.draw_data)
    end

    return true
end

-- !@ 每日免费次数
local get_daily_free_times = function(tdata)
    if not tdata then
        return 0
    end

    local bactive = vip_theme_active()
    if not bactive then
        return 0
    end

    local tcfg = get_vip_theme_cfg()
    if not tcfg then
        return 0
    end

    local max_times = tcfg.max_free_times or 0
    local now = uu.now()
    if not common_uu.is_same_day(now, tdata.free_rcd_time) then
        return max_times
    end

    local get_max_times = tcfg.max_free_times or 0
    return get_max_times - tdata.free_times
end

-- !@ vip每日免费次数
local get_daily_vipfree_times = function(tdata, uin)
    if not tdata then
        return 0
    end

    local bactive = vip_theme_active()
    if not bactive then
        return 0
    end

    local tcfg = get_vip_theme_cfg()
    if not tcfg then
        return 0
    end

    local max_times = tcfg.max_free_times or 0
    local now = uu.now()
    if not common_uu.is_same_day(now, tdata.free_rcd_time) then
        return max_times
    end

    local bVip = FOO.query_mini_vip(uin)
    local get_max_times = tcfg.max_vip_times or 0
    if not bVip then
        return 0
    end
    return get_max_times - tdata.free_times_vip
end

-- !@ 获得赠送次数
local get_present_times = function(tdata)
    if not tdata then
        return 0
    end

    local bactive = vip_theme_active()
    if not bactive then
        return 0
    end

    return tdata.present_times or 0
end

-- !@ 获得可使用的免费次数[每日固定赠送次数(包括每日会员赠送次数)]
local get_free_times = function(tdata, uin)
    return get_daily_free_times(tdata) + get_daily_vipfree_times(tdata, uin)
end


-- !@ 消耗免费次数
-- 优先消耗会员每日赠送次数 >> 全民每日赠送次数 >> 会员激活赠送次数
local use_times = function(tdata, uin, times)
    if times <= 0 then
        log.day_list(FOO.module_name, "use_times param is error!", uu.to_str(tdata), uin, times)
        return error_code.ERROR_PARAM, 0
    end

    local tcfg = get_vip_theme_cfg()
    if not tcfg then
        return error_code.ERROR_CONFIG, 0
    end

    local need_cost = times
    -- 优先消耗每日赠送
    local free_times = get_daily_free_times(tdata)
    if need_cost> 0 and free_times > 0 then
        local real_cost = need_cost
        if free_times < need_cost then
            real_cost = tcfg.max_free_times or 0
        end
        tdata.free_times = tdata.free_times or 0
        tdata.free_times = tdata.free_times + real_cost
        need_cost = need_cost - real_cost
    end

    -- 然后消耗vip每日赠送
    local vipfree_times = get_daily_vipfree_times(tdata, uin)
    if need_cost> 0 and vipfree_times > 0 then
        local real_cost = need_cost
        if vipfree_times < need_cost then
            real_cost = tcfg.max_vip_times or 0
        end
        tdata.free_times_vip = tdata.free_times_vip or 0
        tdata.free_times_vip = tdata.free_times_vip + real_cost
        need_cost = need_cost - real_cost
    end

   return error_code.COMMON_SUCCESS, need_cost
end


-- !@消耗会员续费赠送次数
local use_present_times = function(tdata, times)
    local need_cost = times
    -- 再然后消耗激活VIP赠送次数
    local present_times = get_present_times(tdata)
    if need_cost> 0 and present_times > 0 then
        local real_cost = need_cost
        if present_times < need_cost then
            real_cost = present_times
        end
        tdata.present_times = tdata.present_times or 0
        tdata.present_times = tdata.present_times - real_cost
        need_cost = need_cost - real_cost
    end
    return error_code.COMMON_SUCCESS, need_cost
end

-- !@ 消耗抽奖券
local use_tickets = function(tdata, uin, times)
    if times <= 0 then
        log.day_list(FOO.module_name, "use_tickets param is error!", uu.to_str(tdata), uin, times)
        return error_code.ERROR_PARAM
    end

    local tcfg = get_vip_theme_cfg()
    if not tcfg then
        return error_code.ERROR_CONFIG
    end

    tdata.tickets = tdata.tickets or 0
    if tdata.tickets < times then
        return error_code.TICKET_NOT_ENOUGH
    end
    tdata.tickets = tdata.tickets - times
    return error_code.COMMON_SUCCESS
end

local add_draw_record = function( tdata, item_id, item_num,  time)
    tdata.tdraw_rcd = tdata.tdraw_rcd or {}
    table_insert(tdata.tdraw_rcd , {item_id, item_num, time})
end

--------------------------------------------------
-- !@ 给客户端返回数据
local response_client = function(uin)
    local tcfg = get_vip_theme_cfg()
    if not tcfg then
        return error_code.ERROR_CONFIG
    end

    local tdata = get_data(uin)
    local ret_data = {}
    ret_data.lucky_value = 0
    if tdata.userdata and tdata.userdata["lucky_value"] then  -- 幸运值
        ret_data.lucky_value = tdata.userdata["lucky_value"][tcfg.gift_id] or 0
    end
    ret_data.free_times = get_daily_free_times(tdata)
    ret_data.vipfree_times = get_daily_vipfree_times(tdata, uin)
    ret_data.npresent_times = get_present_times(tdata)
    ret_data.nleft_tickets = tdata.tickets or 0
    ret_data.present_month = tdata.present_month or 0
    ret_data.ticket_price = tcfg.ticket_price
    ret_data.storeid      = tcfg.storeid
    ret_data.start_time   = tcfg.startTime and common_uu.date_to_unix(tcfg.startTime) or 0
    ret_data.endtime      = tcfg.endTime and common_uu.date_to_unix(tcfg.endTime) or 0

    return ret_data
end

--------------------------------------------------
-- !@ 查询玩家是否是会员
FOO.query_mini_vip = function(uin)
    if not ngx.ctx.vip_data then
        local bsucc, tresponse = business_account.query_mini_vip(uin)
        if not bsucc then
            log.day_list(FOO.module_name, "query_mini_vip failed!!  uin=", uin)
            return false
        end

        ngx.ctx.vip_data = tresponse
    end

    local tdata = ngx.ctx.vip_data
    if tdata.end_date < uu.now() then
        return false
    end

    return true
end

--------------------------------------------------
-- !@ 开通会员上报
FOO.payvip_active_sync = function()
    local uin = tonumber(ngx.ctx.m_params.uin) or 0
    local month = tonumber(ngx.ctx.m_params.month) or 0
    local tcfg = get_vip_theme_cfg()
    if not tcfg then
        return error_code.ERROR_CONFIG
    end

    local add_times = tcfg.active_times or 0
    local tdata = get_data(uin)
    tdata.present_month = tdata.present_month or 0
    if tdata.present_month >= tcfg.max_present_month then
        return error_code.COMMON_SUCCESS
    end

    local nRate = month
    if tdata.present_month + month >= tcfg.max_present_month then  --最多赠送多少个月的赠送次数
        nRate = tcfg.max_present_month - tdata.present_month
    end
    local draw_times = add_times * nRate
    tdata.present_month = tdata.present_month + nRate
    tdata.present_times = tdata.present_times or 0
    tdata.present_times = tdata.present_times + draw_times
    local bsuc = set_data(uin, tdata, draw_times > 0)
    if not bsuc then
        log.day_list(FOO.module_name, "payvip_active_sync  save data failed! uin=", uin, "tdata=", uu.to_str(tdata))
        return error_code.ERROR_SYSTEM
    end
    return error_code.COMMON_SUCCESS
end

--------------------------------------------------
-- !@ 获得抽奖界面数据
FOO.get_viptheme_drawdata = function()
    local uin = tonumber(ngx.ctx.m_params.uin) or 0
    return error_code.COMMON_SUCCESS, response_client(uin)
end

--------------------------------------------------
-- !@ 购买抽奖券
FOO.buy_draw_ticket = function()
    local uin = tonumber(ngx.ctx.m_params.uin) or 0
    local num = tonumber(ngx.ctx.m_params.num) or 0
    if uin <= 0 or num <= 0 then
        return error_code.ERROR_PARAM
    end

    local tcfg = get_vip_theme_cfg()
    if not tcfg then
        return error_code.ERROR_CONFIG
    end

    --开始扣除货币-迷你币
    local ext = {
        num = num
    }
    local ret_buy =
        business_account.defray(
        uin,
        business_account.PAYMENTS.MINICOIN,
        tcfg.ticket_price * num,
        "vip_theme_buyticket",
        ext
    )
    if not ret_buy then
        log.day_list(FOO.module_name, "buy_draw_ticket cost failed! uin=", uin, "num=", num, "tcfg=", uu.to_str(tcfg))
        return error_code.ERROR_COST
    end

    --增加券数据
    local tdata = get_data(uin)
    tdata.tickets = tdata.tickets or 0
    tdata.tickets = tdata.tickets + num
    local bsuc = set_data(uin, tdata, true)
    if not bsuc then
        log.day_list(FOO.module_name, "buy_draw_ticket  save data failed! uin=", uin, "tdata=", uu.to_str(tdata))
        return error_code.ERROR_SYSTEM
    end
    return error_code.COMMON_SUCCESS, response_client(uin)
end

--------------------------------------------------
-- !@ 请求抽奖
FOO.request_lucy_draw = function()
    local uin = tonumber(ngx.ctx.m_params.uin) or 0
    local draw_times = tonumber(ngx.ctx.m_params.draw_times) or 0
    if uin <= 0 or draw_times <= 0 then
        return error_code.ERROR_PARAM
    end

    local tcfg = get_vip_theme_cfg()
    if not tcfg then
        return error_code.ERROR_CONFIG
    end
    local tdata = get_data(uin)

    local code, need_cost
    local cost_freetimes = 0
    local cost_presenttimes = 0
    local cost_tickets
    if draw_times == 1 then  -- 单次优先消耗每日赠送次数
        local nleft_times = get_free_times(tdata, uin) + (tdata.tickets or 0)
        if nleft_times < draw_times then
            return error_code.TICKET_NOT_ENOUGH
        end

        code, need_cost = use_times(tdata, uin, draw_times)
        if code ~= error_code.COMMON_SUCCESS then
            return code
        end

        if need_cost ~= draw_times then  --记录消耗的免费次数
            cost_freetimes = draw_times - need_cost
        end
    elseif draw_times == 5 then  -- 5连抽
        local nleft_times = get_present_times(tdata) + (tdata.tickets or 0)
        if nleft_times < draw_times then
            return error_code.TICKET_NOT_ENOUGH
        end
        code, need_cost = use_present_times(tdata, draw_times)
        if code ~= error_code.COMMON_SUCCESS then
            return code
        end

        if need_cost ~= draw_times then --记录消耗的赠送次数
            cost_presenttimes = draw_times - need_cost
        end

    else
        return error_code.ERROR_PARAM
    end

    if need_cost > 0 then
        local code_use = use_tickets(tdata, uin, need_cost)
        if code_use ~= error_code.COMMON_SUCCESS then
            return code
        end
        cost_tickets = need_cost
    else
        cost_tickets = 0
    end

    tdata.userdata = tdata.userdata or {}
    local loginfo = {}
    tdata.userdata.lucky_value = tdata.userdata.lucky_value or {}
    loginfo.lucky_before = tdata.userdata.lucky_value[tcfg.gift_id] or 0
    local ret, drop_items, lucky_value, detail_items = welfare_gift.get_gift(tdata.userdata, tcfg.gift_id, draw_times)
    if ret ~= error_code.COMMON_SUCCESS then
        log.day_list(
            FOO.module_name,
            "request_lucy_draw  get_gift failed! uin=",
            uin,
            "draw_times=",
            draw_times
        )
        return ret
    end

    local _now = uu.now()
    local items = {}
    for _, v in pairs(detail_items or {}) do
        for id, num in pairs(v) do
            items[#items+1] = {id=id, num=num}
            add_draw_record( tdata, id, num,  _now)
        end
    end

    local ret = ns_account.private_account.items_add(items, "vip_theme_luck_draw")
	if not ret then
        log.day_list(FOO.module_name, "request_lucy_draw add_item",  ngx.ctx.m_params.uin, uu.to_str(drop_items), uu.now(), uu.to_str(ret))
		return error_code.ERROR_ADD_ITEM
	end

    loginfo.lucky_after = lucky_value
    loginfo.items = items
    loginfo.cost_ticket = cost_tickets
    loginfo.cost_freetimes = cost_freetimes
    loginfo.cost_presenttimes = cost_presenttimes
    FOO.write_op_log(loginfo)

    local bsuc = set_data(uin, tdata, true)
    if not bsuc then
        log.day_list(FOO.module_name, "request_lucy_draw  save data failed! uin=", uin, "tdata=", uu.to_str(tdata))
        return error_code.ERROR_SYSTEM
    end
    local ret_data = response_client(uin)
    ret_data.items = items
    return error_code.COMMON_SUCCESS, ret_data
end

--------------------------------------------------
-- !@ 请求抽奖记录
FOO.get_draw_prize_record = function()
    local uin = tonumber(ngx.ctx.m_params.uin) or 0
    local tdata = get_data(uin)
    return error_code.COMMON_SUCCESS, tdata.tdraw_rcd or {}
end


FOO.write_op_log = function(loginfo)
    op_log.record("welfare_gift", "request_lucy_draw", loginfo)
end

return FOO
